{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Credits: https://github.com/bansalkanav/Machine_Learning_and_Deep_Learning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pillars of Object Oriented Programming Language\n",
    "\n",
    "In this notebook we will cover below mentioned concepts:\n",
    "1. Inheritance\n",
    "2. Polymorphism\n",
    "3. Abstraction\n",
    "4. Encapsulation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### SUMMARY (OOPs-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T02:30:42.761449Z",
     "start_time": "2018-06-01T02:30:42.721053Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\n\\nInstance Variable: (Object level Variable)\\nThe value of the variable varies from object to object, \\nsuch type of variables are instance variables\\n\\nStatic Variable: (Class level Variable)\\nThese variable are same for all object.\\n\\nLocal Variable: (Method level Variable)\\n\\n'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Class\n",
    "# Object\n",
    "# Reference Variable\n",
    "# Constructor\n",
    "# 'self' Variable\n",
    "# Types of Variables: Instance, Static, Local\n",
    "# Types of Methods: Instance, Class, Static\n",
    "\n",
    "'''\n",
    "Instance Variable: (Object level Variable)\n",
    "The value of the variable varies from object to object, \n",
    "such type of variables are instance variables\n",
    "\n",
    "Static Variable: (Class level Variable)\n",
    "These variable are same for all object.\n",
    "\n",
    "Local Variable: (Method level Variable)\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T06:52:02.355419Z",
     "start_time": "2018-06-01T06:52:02.346394Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Name: abc, RollNo: 1, Marks: 399, College: IIT India\n",
      "{'name': 'abc', 'rno': 1, 'marks': 399}\n",
      "79.80000000000001\n"
     ]
    }
   ],
   "source": [
    "class Student:\n",
    "    college = 'IIT' # Static Variable\n",
    "    def __init__(self, name, rno, marks):\n",
    "        self.name = name # Instance Variable\n",
    "        self.rno = rno # Instance Variable \n",
    "        self.marks = marks # Instance Variable\n",
    "        Student.country = 'India' # Static Variable\n",
    "    \n",
    "    def display(self):\n",
    "        print('Name: {}, RollNo: {}, Marks: {},'.\\\n",
    "              format(self.name, self.rno, self.marks), end=' ')\n",
    "        print('College:', self.college, end=' ')\n",
    "        print(self.country)\n",
    "        \n",
    "        \n",
    "    def getPercentage(self):\n",
    "        total = 500\n",
    "        return (self.marks/total)*100\n",
    "        \n",
    "    def setCollege(self, cname):\n",
    "        self.college = cname\n",
    "        \n",
    "    def getName(self):\n",
    "        return self.name\n",
    "    \n",
    "s1 = Student('abc', 1, 399)\n",
    "\n",
    "s1.display()\n",
    "\n",
    "print(s1.__dict__)\n",
    "\n",
    "print(s1.getPercentage())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Abc:\n",
    "    def __init__(self, n, a):\n",
    "        self.name = n\n",
    "        self.age = a\n",
    "        \n",
    "    def display(self):\n",
    "        print('*'*20)\n",
    "        print(\"Name: \", self.name)\n",
    "        print(\"Age: \", self.age)\n",
    "        print('*'*20)\n",
    "        \n",
    "    @staticmethod\n",
    "    def utility():\n",
    "        print(\"Hello World, this is utility method!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "obj1 = Abc('Kanav', 134234)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "********************\n",
      "Name:  Kanav\n",
      "Age:  134234\n",
      "********************\n"
     ]
    }
   ],
   "source": [
    "obj1.display()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello World, this is utility method!\n"
     ]
    }
   ],
   "source": [
    "obj1.utility()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello World, this is utility method!\n"
     ]
    }
   ],
   "source": [
    "Abc.utility()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "display() missing 1 required positional argument: 'self'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-9-c06fe022c4e9>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mAbc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdisplay\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: display() missing 1 required positional argument: 'self'"
     ]
    }
   ],
   "source": [
    "Abc.display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### @staticmethod can be called with object name as well as class name."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Inheritance\n",
    "\n",
    "Inheritance is the capability of one class to derive or inherit the properties from another class. The benefits of inheritance are:\n",
    "1. It represents real-world **relationships** well.\n",
    "2. It provides **reusability** of a code. We don’t have to write the same code again and again. Also, it allows us to add more features to a class without modifying it.\n",
    "\n",
    "Python allows below mentioned Inheritance concepts:\n",
    "1. Single Inheritance\n",
    "2. Multilevel Inheritance\n",
    "3. Multiple Inheritance (i.e. one child inheriting from multiple parents)\n",
    "4. Herarchical Inheritance (i.e. two childs inheriting from single parent)\n",
    "5. Hybrid Inheritance (Combination of all above - Method Resolution Order i.e. MRO)\n",
    "\n",
    "**MRO (C3 algo)** - In hybrid inheritance, always the methods are resolved Depth first and Left to Right.\n",
    "\n",
    "You can use **super()** to access the constructor and methods of parent class.\n",
    "\n",
    "![Inheritance](img/inheritance.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Single Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Without Inheritance\n",
    "\n",
    "class A:\n",
    "    def m1():\n",
    "        pass\n",
    "    def m2():\n",
    "        pass\n",
    "    \n",
    "class B:\n",
    "    def m1():\n",
    "        pass\n",
    "    def m2():\n",
    "        pass\n",
    "    def m3():\n",
    "        pass\n",
    "    def m4():\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# With Inheritance\n",
    "\n",
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A : Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A : Method-2')\n",
    "    \n",
    "class B(A):\n",
    "    def m3(self):\n",
    "        print('Class-B : Method-3')\n",
    "    def m4(self):\n",
    "        print('Class-B : Method-4')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class-A : Method-1\n",
      "Class-A : Method-1\n",
      "Class-A : Method-2\n",
      "Class-B : Method-3\n"
     ]
    }
   ],
   "source": [
    "a = A()\n",
    "b = B()\n",
    "\n",
    "a.m1()\n",
    "b.m1()\n",
    "b.m2()\n",
    "b.m3()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multilevel Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:01:45.205400Z",
     "start_time": "2018-06-01T07:01:45.198380Z"
    }
   },
   "outputs": [],
   "source": [
    "# Without Inheritance\n",
    "\n",
    "class A:\n",
    "    def m1():\n",
    "        pass\n",
    "    def m2():\n",
    "        pass\n",
    "    \n",
    "class B:\n",
    "    def m1():\n",
    "        pass\n",
    "    def m2():\n",
    "        pass\n",
    "    def m3():\n",
    "        pass\n",
    "    def m4():\n",
    "        pass\n",
    "\n",
    "class C:\n",
    "    def m1():\n",
    "        pass\n",
    "    def m2():\n",
    "        pass\n",
    "    def m3():\n",
    "        pass\n",
    "    def m4():\n",
    "        pass\n",
    "    def m5():\n",
    "        pass\n",
    "    def m6():\n",
    "        pass\n",
    "    \n",
    "# Resolve the error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:07:38.596261Z",
     "start_time": "2018-06-01T07:07:38.582727Z"
    }
   },
   "outputs": [],
   "source": [
    "# With Inheritance\n",
    "\n",
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A : Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A : Method-2')\n",
    "    \n",
    "class B(A):\n",
    "    def m3(self):\n",
    "        print('Class-B : Method-3')\n",
    "    def m4(self):\n",
    "        print('Class-B : Method-4')\n",
    "\n",
    "class C(B):\n",
    "    def m5(self):\n",
    "        print('Class-C : Method-5')\n",
    "    def m6(self):\n",
    "        print('Class-C : Method-6')\n",
    "\n",
    "# How many methods does each class contains now?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:07:44.380486Z",
     "start_time": "2018-06-01T07:07:44.373969Z"
    }
   },
   "outputs": [],
   "source": [
    "a = A()\n",
    "b = B()\n",
    "c = C()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:07:44.380486Z",
     "start_time": "2018-06-01T07:07:44.373969Z"
    },
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# a.m1()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a.m3()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# b.m1()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# b.m4()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multiple Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:18:41.563473Z",
     "start_time": "2018-06-01T07:18:41.557457Z"
    }
   },
   "outputs": [],
   "source": [
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A : Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A : Method-2')\n",
    "    \n",
    "class B:\n",
    "    def m3(self):\n",
    "        print('Class-B : Method-3')\n",
    "    def m4(self):\n",
    "        print('Class-B : Method-4')\n",
    "\n",
    "class C(A, B):\n",
    "    def m5(self):\n",
    "        print('Class-C : Method-5')\n",
    "    def m6(self):\n",
    "        print('Class-C : Method-6')\n",
    "        \n",
    "# Try multilevel + multiple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:18:42.814340Z",
     "start_time": "2018-06-01T07:18:42.809326Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class-A : Method-1\n",
      "Class-B : Method-3\n",
      "Class-C : Method-5\n",
      "Class-A : Method-1\n",
      "Class-B : Method-3\n"
     ]
    }
   ],
   "source": [
    "a = A()\n",
    "b = B()\n",
    "c = C()\n",
    "\n",
    "a.m1()\n",
    "b.m3()\n",
    "c.m5()\n",
    "c.m1()\n",
    "c.m3()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Hierarchical Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A : Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A : Method-2')\n",
    "    \n",
    "class B(A):\n",
    "    def m3(self):\n",
    "        print('Class-B : Method-3')\n",
    "    def m4(self):\n",
    "        print('Class-B : Method-4')\n",
    "\n",
    "class C(A):\n",
    "    def m5(self):\n",
    "        print('Class-C : Method-5')\n",
    "    def m6(self):\n",
    "        print('Class-C : Method-6')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class-A : Method-1\n",
      "Class-A : Method-2\n",
      "Class-B : Method-3\n",
      "Class-C : Method-5\n",
      "Class-A : Method-1\n",
      "Class-A : Method-2\n"
     ]
    }
   ],
   "source": [
    "a = A()\n",
    "b = B()\n",
    "c = C()\n",
    "\n",
    "a.m1()\n",
    "b.m2()\n",
    "b.m3()\n",
    "c.m5()\n",
    "c.m1()\n",
    "c.m2()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Hybrid Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "class A:\n",
    "    pass\n",
    "\n",
    "class B(A):\n",
    "    pass\n",
    "\n",
    "class C(A):\n",
    "    pass\n",
    "\n",
    "class D(B, C):\n",
    "    pass\n",
    "\n",
    "\n",
    "# B and C are inheriting from A - Hierarchical Inheritance\n",
    "# D is inheriting from B and C - Multiple Inheritance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<class '__main__.A'>, <class 'object'>]\n"
     ]
    }
   ],
   "source": [
    "print(A.mro())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<class '__main__.C'>, <class '__main__.A'>, <class 'object'>]\n"
     ]
    }
   ],
   "source": [
    "print(C.mro())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]\n"
     ]
    }
   ],
   "source": [
    "print(D.mro())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### super()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A - Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A - Method-2')\n",
    "        \n",
    "class B:\n",
    "    def m3(self):\n",
    "        super().m1()\n",
    "        print('Class-B - Method-3')\n",
    "    def m4(self):\n",
    "        super().m2()\n",
    "        print('Class-B - Method-4')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a = A()\n",
    "\n",
    "# a.m1()\n",
    "# a.m2()\n",
    "# a.m3()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "# b = B()\n",
    "\n",
    "# b.m3()\n",
    "# b.m4()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Polymorphism\n",
    "\n",
    "Polymorphism means `many forms`.\n",
    "\n",
    "Below mentioned topics are majorly discussed with polymorphism:\n",
    "\n",
    "1. Dynamically typed or Duck Typing\n",
    "2. Overloading\n",
    "    - Operator Overloading\n",
    "    - Method Overloading (Not supported)\n",
    "    - Constructor Overloading (Not supported)\n",
    "3. Overriding\n",
    "    - Method Overriding\n",
    "    - Constructor Overriding"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Operator Overloading "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:22:30.025980Z",
     "start_time": "2018-06-01T07:22:30.014951Z"
    }
   },
   "outputs": [],
   "source": [
    "# # Operator Overloading\n",
    "\n",
    "# class A:\n",
    "#     def __init__(self, num):\n",
    "#         self.num = num\n",
    "        \n",
    "# a1 = A(10)\n",
    "# a2 = A(20)\n",
    "\n",
    "# print(a1+a2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:26:46.273550Z",
     "start_time": "2018-06-01T07:26:46.268535Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "30\n"
     ]
    }
   ],
   "source": [
    "class A:\n",
    "    def __init__(self, num):\n",
    "        self.num = num\n",
    "    \n",
    "    def __add__(self, other):\n",
    "        return self.num + other.num\n",
    "        \n",
    "a1 = A(10)\n",
    "a2 = A(20)\n",
    "\n",
    "print(a1+a2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Method Overloading"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:32:41.181981Z",
     "start_time": "2018-06-01T07:32:41.159426Z"
    }
   },
   "outputs": [],
   "source": [
    "class A:\n",
    "    def m(self):\n",
    "        print('no-arg method')\n",
    "    \n",
    "    def m(self, a):\n",
    "        print('one arg method')\n",
    "    \n",
    "    def m(self, a, b):\n",
    "        print('two arg method')\n",
    "        \n",
    "a = A()\n",
    "\n",
    "# a.m()\n",
    "\n",
    "# a.m(10)\n",
    "\n",
    "# a.m(10, 20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constructor Overloading"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:35:44.331747Z",
     "start_time": "2018-06-01T07:35:44.319213Z"
    }
   },
   "outputs": [],
   "source": [
    "class MyClass:\n",
    "\n",
    "    def __init__(self, a, b):\n",
    "        print('parameterized')\n",
    "        \n",
    "    def __init__(self):\n",
    "        print('constructor with no parameter')\n",
    "        \n",
    "# m1 = MyClass()\n",
    "\n",
    "# m2 = MyClass(1, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# class Test:\n",
    "#     def __init__(self):\n",
    "#         print('Constructor-1 is executed')\n",
    "        \n",
    "#     def __init__(self):\n",
    "#         print('Constructor-2 is executed')\n",
    "        \n",
    "#     def __init__(self, a):\n",
    "#         print('Constructor-3 is executed')\n",
    "        \n",
    "#     def __init__(self, a, b):\n",
    "#         print('Constructor-4 is executed')\n",
    "        \n",
    "#     def fun(self):\n",
    "#         print('Function is executed')\n",
    "        \n",
    "# t1 = Test()\n",
    "# t1.fun()\n",
    "\n",
    "# t2 = Test(5, 12)\n",
    "# t2.fun()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Method Overriding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:58:10.133600Z",
     "start_time": "2018-06-01T07:58:10.125576Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class-A : Method-1\n",
      "Class-B : Method-1\n"
     ]
    }
   ],
   "source": [
    "class A:\n",
    "    def m1(self):\n",
    "        print('Class-A : Method-1')\n",
    "    def m2(self):\n",
    "        print('Class-A : Method-2')\n",
    "    \n",
    "class B(A):\n",
    "    def m1(self):\n",
    "        super().m1()\n",
    "        print('Class-B : Method-1')\n",
    "        \n",
    "b = B()\n",
    "\n",
    "b.m1()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constructor Overriding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-06-01T07:56:32.993453Z",
     "start_time": "2018-06-01T07:56:32.988439Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parent Constructor\n",
      "Child Constructor\n"
     ]
    }
   ],
   "source": [
    "class A:\n",
    "    def __init__(self):\n",
    "        print('Parent Constructor')\n",
    "        \n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        print('Child Constructor')\n",
    "        \n",
    "b = B()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class A:\n",
    "    \n",
    "    def m1(self):\n",
    "        print(\"hi\")\n",
    "        \n",
    "    def m1(self, name):\n",
    "        print(\"hi\", name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hi Kanav\n"
     ]
    }
   ],
   "source": [
    "a = A()\n",
    "\n",
    "a.m1(\"Kanav\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a.m1()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example 1 : Create `Rectangle` and `Circle` which would be a `Shape`. Every shape (or object) that user create, should have a name, color and area properties. User should have a flexibility to change the color of any shape, calculate area and display the properties of each shape."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Write your solutions and submit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Benefits of OOPs\n",
    "\n",
    "1. Restricted access to class members through `Access Modifiers`.\n",
    "2. Code reuse with the help of `Inheritance`.\n",
    "3. Flexibility to have methods with separate signature through `Polymorphism`.\n",
    "4. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Assignments"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Q-1 Create a class Animal as a base class and define method animal_attribute. Create another class Tiger which is inheriting Animal and access the base class method.\n",
    "\n",
    "Q-3 Create a class Cop. Initialize its name, age , work experience. Define methods to  display and update the details. Create another class Mission which extends the class Cop.\n",
    "\n",
    "  Define method add_mission _details. Select an object of Cop and access methods of base class to get information for a particular cop and make it available for mission. \n",
    "\n",
    "\n",
    "Q-4 Create a class Shape.Initialize it with length and breadth Create the method Area. Create class rectangle and square which inherits shape and access the method Area."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.6"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
